package com.ruoyi.warning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.warning.domain.entity.Device;
import com.ruoyi.warning.domain.entity.Property;
import com.ruoyi.warning.domain.entity.PropertyVminfoLog;
import com.ruoyi.warning.domain.http.OidDisk;
import com.ruoyi.warning.domain.http.OidProcess;
import com.ruoyi.warning.mapper.PropertyVminfoLogMapper;
import com.ruoyi.warning.service.IDevicesService;
import com.ruoyi.warning.service.IPropertyService;
import com.ruoyi.warning.service.IPropertyVminfoLogService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p>
 * 虚拟机资产日志表 服务实现类
 * </p>
 *
 * @author chenhc
 * @since 2025-08-28
 */
@Service
public class PropertyVminfoLogServiceImpl extends ServiceImpl<PropertyVminfoLogMapper, PropertyVminfoLog> implements IPropertyVminfoLogService {

    @Resource
    private IPropertyService propertyService;
    @Resource
    private IDevicesService devicesService;
    @Override
    public void refresh() {
        //找到所有虚拟机的资产
        List<Property> properties = propertyService.list(new LambdaQueryWrapper<Property>()
                .in(Property::getSystemType, Arrays.asList(2, 3)));
        for(Property property: properties){
            if(property.getSystemType().equals(3)){
                addVminfoLog(property);
            }else {
                addVminfoLogLinux(property);
            }
        }
    }

    private void addVminfoLogLinux(Property property) {
        Device device = devicesService.getOne(new QueryWrapper<Device>().lambda().eq(Device::getHostname,property.getHostname()).last("limit 1"));
        if(device == null){
            return;
        }
        PropertyVminfoLog log = new PropertyVminfoLog();
        log.setPropertyId(property.getPropertyId());
        List<String> cpuList = getCmdList(".1.3.6.1.4.1.2021.11.9.0",device);
        //cpu利用率
        if (cpuList != null && !cpuList.isEmpty()) {
            int sum = 0;
            int count = 0;
            for (String cpu : cpuList) {
                try {
                    sum += Integer.valueOf(cpu);
                    count++;
                } catch (NumberFormatException e) {
                    System.err.println("无法解析CPU数值: " + cpu);
                }
            }
            if (count > 0) {
                int average = sum / count;
                log.setProcessorsUsage(average);
            }
        }
        //内存利用率
        int memoryTotal = 0 ;
        int memoryUsed = 0 ;
        String memoryTotalString = getCmdString("1.3.6.1.4.1.2021.4.5.0",device);
        String memoryUsedString = getCmdString("1.3.6.1.4.1.9600.1.1.2.3",device);
        if(ObjectUtils.isNotEmpty(memoryTotalString)) memoryTotal = Integer.valueOf(memoryTotalString);
        if(ObjectUtils.isNotEmpty(memoryUsedString)) memoryUsed = Integer.valueOf(memoryUsedString);
        // 安全计算内存使用率，避免除零异常
        if (memoryTotal > 0) {
            log.setMemoryUsage(memoryUsed * 100 / memoryTotal);
        } else {
            log.setMemoryUsage(0);
        }        //读写IOPS
        //先找到所有盘
        List<String> diskList = getCmdList("1.3.6.1.4.1.2021.13.15.1.1.2",device);
        List<String> readList = getCmdList("1.3.6.1.4.1.2021.13.15.1.1.5",device);
        List<String> writeList = getCmdList("1.3.6.1.4.1.2021.13.15.1.1.6",device);
        //进程等待一秒钟
         try {
             Thread.sleep(1000);
         } catch (InterruptedException e) {
             throw new RuntimeException(e);
         }
        List<String> readListNow = getCmdList("1.3.6.1.4.1.2021.13.15.1.1.5",device);
        List<String> writeListNow = getCmdList("1.3.6.1.4.1.2021.13.15.1.1.6",device);

        for(int i=0;i<diskList.size();i++){
            if("_Total".equals(diskList.get(i))){
                log.setReadIops(Integer.valueOf(readListNow.get(i))-Integer.valueOf(readList.get(i)));
                log.setWriteIops(Integer.valueOf(writeListNow.get(i))-Integer.valueOf(writeList.get(i)));
                break;
            }
        }
        this.save(log);
    }


    private void addVminfoLog(Property property) {
        Device device = devicesService.getOne(new QueryWrapper<Device>().lambda().eq(Device::getHostname,property.getHostname()).last("limit 1"));
        if(device == null){
            return;
        }
        PropertyVminfoLog log = new PropertyVminfoLog();
        log.setPropertyId(property.getPropertyId());
        List<String> cpuList = getCmdList("1.3.6.1.4.1.9600.1.1.5.1.5",device);
        //cpu利用率
        if (cpuList != null && !cpuList.isEmpty()) {
            int sum = 0;
            int count = 0;
            for (String cpu : cpuList) {
                try {
                    sum += Integer.valueOf(cpu);
                    count++;
                } catch (NumberFormatException e) {
                    System.err.println("无法解析CPU数值: " + cpu);
                }
            }
            if (count > 0) {
                int average = sum / count;
                log.setProcessorsUsage(average);
            }
        }
        //内存利用率
        int memoryTotal = 0 ;
        int memoryFree = 0 ;
        String memoryTotalString = getCmdString("1.3.6.1.2.1.25.2.2.0",device);
        String memoryFreeString = getCmdString("1.3.6.1.4.1.9600.1.1.2.3",device);
        if(ObjectUtils.isNotEmpty(memoryTotalString)) memoryTotal = Integer.valueOf(memoryTotalString);
        if(ObjectUtils.isNotEmpty(memoryFreeString)) memoryFree = Integer.valueOf(memoryFreeString);
        if(memoryTotal!=0){
            log.setMemoryUsage(Integer.valueOf((memoryTotal-memoryFree*1024)*100/memoryTotal));
        }
        //读写IOPS
        //先找到所有盘
        List<String> diskList = getCmdList("1.3.6.1.4.1.9600.1.1.1.1.1",device);
        List<String> readList = getCmdList("1.3.6.1.4.1.9600.1.1.1.1.16",device);
        List<String> writeList = getCmdList("1.3.6.1.4.1.9600.1.1.1.1.19",device);
        for(int i=0;i<diskList.size();i++){
            if("_Total".equals(diskList.get(i))){
                log.setReadIops(Integer.valueOf(readList.get(i)));
                log.setWriteIops(Integer.valueOf(writeList.get(i)));
                break;
            }
        }
        this.save(log);
    }

    @Override
    public Object getOidProcessList(String hostname) {
        Device device = devicesService.getOne(new QueryWrapper<Device>().lambda().eq(Device::getHostname,hostname).last("limit 1"));
        if(device == null){
            return null;
        }
        List<OidProcess> oidProcesses = new ArrayList<>();
        List<String> idList = getCmdList("1.3.6.1.2.1.25.4.2.1.1",device);
        List<String> nameList = getCmdList("1.3.6.1.2.1.25.4.2.1.2",device);
        List<String> pathList = getCmdList("1.3.6.1.2.1.25.4.2.1.4",device);
        for(int i=0;i<idList.size();i++){
            OidProcess oidProcess = new OidProcess();
            oidProcess.setId(idList.get(i));
            oidProcess.setName(nameList.get(i));
            oidProcess.setPath(pathList.get(i));
            oidProcesses.add(oidProcess);
        }
        return oidProcesses;
    }

    @Override
    public Object getOidDiskList(String hostname) {
        Device device = devicesService.getOne(new QueryWrapper<Device>().lambda().eq(Device::getHostname,hostname).last("limit 1"));
        if(device == null){
            return null;
        }
        List<OidDisk> oidDisk = new ArrayList<>();
        List<String> nameList = getCmdList("1.3.6.1.4.1.9600.1.1.1.1.1",device);
        List<String> readTimePercentList = getCmdList("1.3.6.1.4.1.9600.1.1.1.1.2",device);
        List<String> writeTimePercentList = getCmdList("1.3.6.1.4.1.9600.1.1.1.1.4",device);
        List<String> totalTimePercentList = getCmdList("1.3.6.1.4.1.9600.1.1.1.1.3",device);
        List<String> usageSpacePercentList = getCmdList("1.3.6.1.4.1.9600.1.1.1.1.5",device);
        List<String> totalThroughputList = getCmdList("1.3.6.1.4.1.9600.1.1.1.1.14",device);
        List<String> readBytesPerSecondList = getCmdList("1.3.6.1.4.1.9600.1.1.1.1.15",device);
        List<String> readOperationsPerSecondList = getCmdList("1.3.6.1.4.1.9600.1.1.1.1.16",device);
        List<String> readWriteOperationsPerSecondList = getCmdList("1.3.6.1.4.1.9600.1.1.1.1.17",device);
        List<String> writeBytesPerSecondList = getCmdList("1.3.6.1.4.1.9600.1.1.1.1.18",device);
        List<String> writeOperationsPerSecondList = getCmdList("1.3.6.1.4.1.9600.1.1.1.1.19",device);
        List<String> freeSpaceMBList = getCmdList("1.3.6.1.4.1.9600.1.1.1.1.20",device);

        for(int i=0;i<nameList.size();i++){
            OidDisk disk = new OidDisk();
            disk.setName(nameList.get(i));
            disk.setReadTimePercent(readTimePercentList.get(i));
            disk.setWriteTimePercent(writeTimePercentList.get(i));
            disk.setTotalTimePercent(totalTimePercentList.get(i));
            disk.setUsageSpacePercent(
                    String.valueOf(100-Integer.valueOf(usageSpacePercentList.get(i)))
            );
            disk.setTotalThroughput(totalThroughputList.get(i));
            disk.setReadBytesPerSecond(readBytesPerSecondList.get(i));
            disk.setReadOperationsPerSecond(readOperationsPerSecondList.get(i));
            disk.setReadWriteOperationsPerSecond(readWriteOperationsPerSecondList.get(i));
            disk.setWriteBytesPerSecond(writeBytesPerSecondList.get(i));
            disk.setWriteOperationsPerSecond(writeOperationsPerSecondList.get(i));
            disk.setFreeSpaceMB(freeSpaceMBList.get(i));
            oidDisk.add(disk);
        }
        return oidDisk;
    }

    private String getCmdString(String oid,Device device){
        String result = "";
        try {
            // 构建命令数组（避免空格分割问题）
            String[] cmd = {"snmpwalk", "-"+device.getSnmpver(), "-c", device.getCommunity(), device.getHostname(), oid};
            // 创建进程
            Process process = Runtime.getRuntime().exec(cmd);
            // 读取标准输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                System.out.println("++++++++++++++++++++");
                System.out.println(line);
                // 找到第一个 ": " 的位置
                int index = line.indexOf(": ");
                if (index != -1) {
                    // 从 ": " 之后截取字符串
                    result = line.substring(index + 2);
                    // 去掉双引号
                    result = result.replace("\"", "");
                }
            }
            // 读取错误输出
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            while ((line = errorReader.readLine()) != null) {
                System.out.println("=====================");
                System.err.println(line);
                return null;
            }
            // 等待进程结束并获取退出码
            int exitCode = process.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }
    private List<String> getCmdList(String oid, Device device){
        List<String> list = new ArrayList<>();
        try {
            // 构建命令数组（避免空格分割问题）
            String[] cmd = {"snmpwalk", "-v2c", "-c", device.getCommunity(), device.getHostname(), oid};
            // 创建进程
            Process process = Runtime.getRuntime().exec(cmd);
            // 读取标准输出
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            int index;
            while ((line = reader.readLine()) != null) {
                System.out.println("++++++++++++++++++++");
                System.out.println(line);
                // 找到第一个 ": " 的位置
                index = line.indexOf(": ");
                if (index != -1) {
                    // 从 ": " 之后截取字符串
                    line = line.substring(index + 2);
                    // 去掉双引号
                    list.add(line.replace("\"", ""));
                }
            }
            // 读取错误输出
            BufferedReader errorReader = new BufferedReader(new InputStreamReader(process.getErrorStream()));
            while ((line = errorReader.readLine()) != null) {
                System.out.println("=====================");
                System.err.println(line);
                return null;
            }
            // 等待进程结束并获取退出码
            int exitCode = process.waitFor();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }
}
